unit Chromium4D.Extension;

interface

  uses System.Classes, System.SysUtils, System.Generics.Collections, System.Generics.Defaults
    , ceflib
    , Chromium4D.Classes
    , Chromium4D.Core
    , Chromium4D.Render.Environment
    ;


const

  EXTENSION_MODULES: array[0..18, 0..1] of string =
    (
      ('assert', ''),
      ('buffer', ''),
      ('constans', ''),
      ('events', ''),
      ('fs', ''),
      ('module', ''),
      ('os', ''),
      ('path', ''),
      ('process', ''),
      ('punycode', ''),
      ('querystring', ''),
      ('string_decoder', ''),
      ('timers', ''),
      ('url', ''),
      ('vm', ''),
      ('internal/cluster', ''),
      ('internal/freelist', ''),
      ('internal/module', ''),
      ('internal/util', '')
    );

type

  TSyV8ExtPropertyAccessor = class(TCefV8AccessorOwn)
  protected
    function Get(const name: ustring; const obj: ICefv8Value; out value: ICefv8Value;
      const exception: ustring): Boolean; override;
    function Put(const name: ustring; const obj, value: ICefv8Value; const exception: ustring): Boolean; override;
  end;


  TSyJavascriptMethodCallBack = function(const obj: ICefv8Value; const arguments: TCefv8ValueArray;
      var retval: ICefv8Value; var exception: ustring): Boolean of object;

  TSyV8ExtHandler = class(TCefv8HandlerOwn)
  protected
    FEnv: TSyRenderEnvironment;
    FJavascriptMethodMapper: TDictionary<string, TSyJavascriptMethodCallBack>;
  protected
    function Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray;
      var retval: ICefv8Value; var exception: ustring): Boolean; override;
  protected
    procedure DefineObjectFunction(Ref: ICefv8Value; Name: string; CallBack: TSyJavascriptMethodCallBack);
    procedure DefineObjectAccessor(Ref: ICefv8Value; Name: string; Accessor: TSyV8ExtPropertyAccessor);
  public
    constructor Create; override;
    destructor Destroy; override;
  public
    class function ObjectFactory(process: TSyChromiumProcess; env: TSyRenderEnvironment; context: ICefv8Context): ICefv8Value; virtual;
    class procedure ObjectBuilder(process: TSyChromiumProcess; env: TSyRenderEnvironment; context: ICefv8Context; target: ICefv8Value); virtual;
  end;
  TSyV8ExtHandlerClass = class of TSyV8ExtHandler;



implementation

  uses Chromium4D.Utils;

{ TSyV8ExtHandler }

constructor TSyV8ExtHandler.Create;
begin
  inherited;
  FJavascriptMethodMapper := TDictionary<string, TSyJavascriptMethodCallBack>.Create();
end;

procedure TSyV8ExtHandler.DefineObjectAccessor(Ref: ICefv8Value; Name: string; Accessor: TSyV8ExtPropertyAccessor);
var
  obj: ICefv8Value;
begin
  obj := TCefv8ValueRef.NewObject(Accessor);
  Ref.SetValueByKey(Name, obj, V8_PROPERTY_ATTRIBUTE_NONE);
end;

procedure TSyV8ExtHandler.DefineObjectFunction(Ref: ICefv8Value; Name: string; CallBack: TSyJavascriptMethodCallBack);
begin
  FJavascriptMethodMapper.Add(Name, CallBack);
  Ref.SetValueByKey(Name, TCefv8ValueRef.NewFunction(Name, Self), V8_PROPERTY_ATTRIBUTE_NONE);
end;

destructor TSyV8ExtHandler.Destroy;
begin
  if Assigned(FJavascriptMethodMapper) then
    FreeAndNil(FJavascriptMethodMapper);
  inherited;
end;

function TSyV8ExtHandler.Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray;
  var retval: ICefv8Value; var exception: ustring): Boolean;
var
  CallBack: TSyJavascriptMethodCallBack;
begin
  if not FJavascriptMethodMapper.TryGetValue(name, CallBack) then
  begin
    exception := Format('find callbakc %s failed', [name]);
    Logger.Error(TCefThreadHelper.CheckCurrentThread + ' | ' + exception);
    Exit(True)
  end;

  Result := CallBack(obj, arguments, retval, exception);
end;

class procedure TSyV8ExtHandler.ObjectBuilder(process: TSyChromiumProcess; env: TSyRenderEnvironment;
  context: ICefv8Context; target: ICefv8Value);
begin

end;

class function TSyV8ExtHandler.ObjectFactory(process: TSyChromiumProcess; env: TSyRenderEnvironment;
  context: ICefv8Context): ICefv8Value;
begin

end;

{ TSyV8ExtPropertyAccessor }

function TSyV8ExtPropertyAccessor.Get(const name: ustring; const obj: ICefv8Value; out value: ICefv8Value;
  const exception: ustring): Boolean;
begin

end;

function TSyV8ExtPropertyAccessor.Put(const name: ustring; const obj, value: ICefv8Value;
  const exception: ustring): Boolean;
begin

end;

end.
